--- 定时器模块
--@script common.base.timer

local math = math
local debug = debug

local M = class("ctimer")


function M:ctor()
    self.timers = {}
    self.id = 0
end

--- 开启定时器
--@param[type=int] interval 定时器超时值(单位为1秒)
--@param[type=func] callback 超时回调函数
--@param[type=int] count 执行次数   count = -1 表示无限次
--@return[type=int] 定时器ID
function M:timeout(interval, callback, count, ...)
    interval = interval < 0 and 0 or interval
    count = count or 1
    local id = self:addTimer(interval, callback, count, ...)
    g.timeout(interval, function()
        self:ontimeout(id)
    end)
    --g.log:debug("addTimer", id)
    return id
end

-- private method
function M:genid()
    repeat
        self.id = self.id + 1
    until self.timers[self.id] == nil
    return self.id
end

function M:getCurrId()
    return self.id
end

function M:addTimer(interval, callback, count, ...)
    local id = self:genid()
    local timer_obj = {
        id = id,
        interval = interval, --math.tointeger(interval) or 0,
        count = math.tointeger(count) or 0,
        start_time = g.time(),
        callback = callback,
        arg = {...}
    }
    self.timers[id] = timer_obj
    return id
end

function M:getTimer(id)
    if not id then return end
    return self.timers[id]
end

-- 根据ID取消定时器
-- @param[type=int] id 定时器ID
function M:deltimer(id)
    if not id then return end
    local timer_obj = self:getTimer(id)
    if not timer_obj then
        return
    end
    --g.log:info("deltimer:", id)
    self.timers[id] = nil
end

function M:ontimeout(id)
    if not id then return end
    local timer_obj = self:getTimer(id)
    if not timer_obj then
        return
    end
    if timer_obj.count > 0 then
        timer_obj.count = timer_obj.count - 1
    end
    timer_obj.start_time = 0
    if timer_obj.count ~= 0 then
        g.timeout(timer_obj.interval, function() self:ontimeout(id) end)
    end
    local callback = timer_obj.callback
    local arg = timer_obj.arg
    if callback then
        local ok, res = xpcall(callback, debug.traceback, table.unpack(arg))
        if not ok then
            g.log:err("timer err:", id, timer_obj, res)
        end
    end
    if timer_obj.count == 0 then
        self:deltimer(id)
    end
end

--剩余时间
function M:getCD(id)
    local timer_obj = self:getTimer(id)
    if not timer_obj then
        return 0
    end
    local delay = timer_obj.interval - (g.time() - timer_obj.start_time)
    if delay < 0 then
        delay = 0
    end
    return delay
end

return M